package cn.brian.modular.drools.test;

import cn.brian.modular.framework.drools.component.KieTemplate;
import cn.brian.modular.sys.entity.SysUser;
import org.drools.core.event.DebugRuleRuntimeEventListener;
import org.drools.decisiontable.InputType;
import org.drools.decisiontable.SpreadsheetCompiler;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.*;
import org.kie.api.io.Resource;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.StatelessKieSession;
import org.kie.internal.utils.KieHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by ming on 2018/5/24.
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class TesRules {


    @Test
    public void testFileRule() throws Exception{
        // 设置时间格式
        System.setProperty("drools.dateformat", "yyyy-MM-dd");

        KieServices kieServices = KieServices.Factory.get();
        KieFileSystem kfs = kieServices.newKieFileSystem();
        Resource resource = kieServices.getResources().newFileSystemResource("src/main/resources/drools/rules/test.drl");
        resource.setResourceType(ResourceType.DRL);
        kfs.write(resource);
        KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
        if (kieBuilder.getResults().getMessages(Message.Level.ERROR).size() > 0) {
            throw new RuntimeException(kieBuilder.getResults().getMessages().toString());
        }
        KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
        KieBase kBase = kieContainer.getKieBase();

        KieSession kieSession = kBase.newKieSession();
        kieSession.addEventListener(new DebugRuleRuntimeEventListener());
        List<SysUser> list = getStus();
        for (SysUser stu : list) {
            kieSession.insert(stu);
        }
        kieSession.fireAllRules();
        kieSession.dispose();
        System.out.println("end....");
    }

    @Test
    public void testMain()  throws Exception{

        // 设置时间格式
        System.setProperty("drools.dateformat", "yyyy-MM-dd");
        //为防止规则文件名字重复，此处加上时间戳( 格式：场景标识+时间戳+.drl)
        String ruleFileName = System.currentTimeMillis() + ".drl";

        KieServices kieServices = KieServices.Factory.get();
        KieFileSystem kfs = kieServices.newKieFileSystem();
        kfs.write("src/main/resources/drools/rules/test.drl","UTF-8");
        KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
        if (kieBuilder.getResults().getMessages(Message.Level.ERROR).size() > 0) {
            throw new RuntimeException(kieBuilder.getResults().getMessages().toString());
        }
        KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
        KieBase kBase = kieContainer.getKieBase();

        KieSession kieSession = kBase.newKieSession();
        kieSession.addEventListener(new DebugRuleRuntimeEventListener());

        List<SysUser> list = getStus();
        for (SysUser stu : list) {
            kieSession.insert(stu);
        }
        kieSession.fireAllRules();
        kieSession.dispose();
        System.out.println("end....");
    }

    public static List<SysUser> getStus() {
        List<SysUser> stus = new ArrayList<>();
        stus.add(SysUser.builder().age(16).userName("张三").sex("1").build());
        stus.add(SysUser.builder().age(18).userName("huhu").sex("1").build());

        stus.add(SysUser.builder().age(32).userName("王五").sex("1").build());

        stus.add(SysUser.builder().age(23).userName("张红").sex("2").build());

        stus.add(SysUser.builder().age(35).userName("李四").sex("1").build());

        stus.add(SysUser.builder().age(31).userName("张小雅").sex("2").build());

        return stus;
    }

    //@Test
    public  void getAllRules() throws Exception {
        try {
            KieServices kieServices = KieServices.Factory.get();
            KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
            for (org.springframework.core.io.Resource file : new PathMatchingResourcePatternResolver().getResources("classpath*:" + "drools/rules/" + "**/*.*")) {
                System.out.println(file.getFilename());
                kieFileSystem.write(org.kie.internal.io.ResourceFactory.newClassPathResource("drools/rules"  + file.getFilename(), "UTF-8"));
            }
            final KieRepository kieRepository = KieServices.Factory.get().getRepository();
            kieRepository.addKieModule(new KieModule() {
                @Override
                public ReleaseId getReleaseId() {
                    return kieRepository.getDefaultReleaseId();
                }
            });
            KieBuilder kieBuilder = KieServices.Factory.get().newKieBuilder(kieFileSystem);
            kieBuilder.buildAll();
            KieSession kieSession = KieServices.Factory.get().newKieContainer(kieRepository.getDefaultReleaseId()).newKieSession().getKieBase().newKieSession();

        } catch (Exception ex) {
            throw ex;
        }
    }

    /**
     * @param classPath 绝对路径
     * @return KieSession 有状态
     * @description TODO (快速新建KieSession)
     */
    public static KieSession newKieSession(String classPath) throws Exception {
        KieSession kieSession = getKieBase(classPath).newKieSession();
        kieSession.addEventListener(new DebugRuleRuntimeEventListener());
        return kieSession;

    }

    /**
     * @param classPath 绝对路径
     * @return StatelessKieSession 无状态
     * @description TODO (快速新建StatelessKieSession)
     */
    public static StatelessKieSession newStatelessKieSession(String classPath) throws Exception {
        StatelessKieSession kiesession = getKieBase(classPath).newStatelessKieSession();
        return kiesession;

    }

    /**
     * @return void
     * @description TODO (清空对象)
     * @title disposeKieSession 重置KieSession
     */
//    public static void disposeKieSession() {
//        if (kieSession != null) {
//            kieSession.dispose();
//            kieSession = null;
//        }
//    }

    protected static KieBase getKieBase(String classPath) throws Exception {
        KieServices kieServices = KieServices.Factory.get();
        KieFileSystem kfs = kieServices.newKieFileSystem();
        Resource resource = kieServices.getResources().newClassPathResource(classPath);
        resource.setResourceType(ResourceType.DRL);
        kfs.write(resource);
        KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
        if (kieBuilder.getResults().getMessages(Message.Level.ERROR).size() > 0) {
            throw new Exception();
        }
        KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
        KieBase kBase = kieContainer.getKieBase();
        return kBase;
    }

    /**
     * 根据服务器真实路径下的xls文件生成drl文件内容
     */
    public static KieSession getKieSessionFromXLS(String realPath) throws FileNotFoundException {
        return createKieSessionFromDRL(getDRL(realPath));
    }

    // 把xls文件解析为String
    public static String getDRL(String realPath) throws FileNotFoundException {
        File file = new File(realPath); // 例如：C:\\abc.xls
        InputStream is = new FileInputStream(file);
        SpreadsheetCompiler compiler = new SpreadsheetCompiler();
        return compiler.compile(is, InputType.XLS);
    }

    // drl为含有内容的字符串
    public static KieSession createKieSessionFromDRL(String drl) {
        KieHelper kieHelper = new KieHelper();
        kieHelper.addContent(drl, ResourceType.DRL);
        Results results = kieHelper.verify();
        if (results.hasMessages(Message.Level.WARNING, Message.Level.ERROR)) {
            List<Message> messages = results.getMessages(Message.Level.WARNING, Message.Level.ERROR);
            for (Message message : messages) {
                System.out.println("Error: " + message.getText());
            }
            throw new IllegalStateException("Compilation errors were found. Check the logs.");
        }
        return kieHelper.build().newKieSession();
    }


    @Test
    public void ruleStringTest() throws Exception {

        String myRule = "import cn.brian.modular.sys.entity.SysUser\n" +
                "\n" +
                "dialect  \"mvel\"\n" +
                "\n" +
                "rule \"age\"\n" +
                "    when\n" +
                "        $person : SysUser(age<16 || age>50)\n" +
                "    then\n" +
                "        System.out.println(\"这个人的年龄不符合要求！（基于动态加载）\");\n" +
                "end\n";

        KieHelper helper = new KieHelper();

        helper.addContent(myRule, ResourceType.DRL);

        KieSession ksession = helper.build().newKieSession();

        SysUser person = new SysUser();

        person.setAge(17);

        ksession.insert(person);

        ksession.fireAllRules();

        ksession.dispose();
    }

}